package completeFuture;

import completeFuture.domain.Shop;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 对线程数的思考：
 * 1、对于计算密集型的，线程数等于处理器个数，这样既能保证全部处理器都用起来，又可以减少切换上下文的开销
 * 2、对于IO密集型，线程可以多开，大于处理器个数，这样可以避免cpu在IO等待时没事做
 */
public class ShopTest {

    List<Shop> list;

    @Test
    public void oneTest() throws ExecutionException, InterruptedException {
        Shop shop = new Shop("涂式商品");
        System.out.println(shop.getPrice("洗发露"));
        System.out.println(shop.getPriceAsyn("洗发露").get());
    }

    @Test
    public void manyTest() {
        list = Arrays.asList(
                new Shop("1号商店"),
                new Shop("2号商店"),
                new Shop("3号商店"),
                new Shop("4号商店"),
                new Shop("5号商店"),
                new Shop("6号商店"),
                new Shop("7号商店"),
                new Shop("8号商店"),
                new Shop("9号商店")
        );
        List<String> 洗发露 = findPrices4("洗发露");
        洗发露.stream().forEach(System.out::println);
    }

    public List<String> findPrices(String product) {
        return list.stream()
                .map(shop -> shop.getPrice(product))
                .collect(Collectors.toList());
    }

    /**
     * parallelStream默认线程数量Runtime.getRuntime().availableProcessors()
     * @param product
     * @return
     */
    public List<String> findPrices2(String product) {
        return list.parallelStream()
                .map(shop -> shop.getPrice(product))
                .collect(Collectors.toList());
    }

    /**
     * CompletableFuture默认线程数量Runtime.getRuntime().availableProcessors()
     * @param product
     * @return
     */
    public List<String> findPrices3(String product) {
        List<CompletableFuture<String>> collect = list.stream()
                .map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product)))
                .collect(Collectors.toList());

        return collect.stream()
                .map(item -> item.join())
                .collect(Collectors.toList());
    }

    /**
     * 定制线程数量
     * @param product
     * @return
     */
    public List<String> findPrices4(String product) {

        //定制化线程池
        ExecutorService executor = Executors.newFixedThreadPool(Math.min(list.size(), 100),
                r -> {
                    Thread thread = new Thread(r);
                    thread.setDaemon(true);
                    return thread;
                });
        List<CompletableFuture<String>> collect = list.stream()
                .map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor))
                .collect(Collectors.toList());

        List<String> stringList = collect.stream()
                .map(item -> item.join())
                .collect(Collectors.toList());
        executor.shutdown();
        return stringList;
    }
}
